//==================================================================
//  Copyright (C) 2006-2007  Davide Pasca
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//==================================================================
/// @file	psys_stdgfx.h
///
///
///
//==================================================================

#ifndef PSYS_GFXBASE_H
#define PSYS_GFXBASE_H

namespace PSYSGFX
{
	enum Culling
	{
		CULL_CW,
		CULL_CCW,
		CULL_OFF,
	};

	enum TestFunc
	{
		TESTFUNC_NEVER,
		TESTFUNC_LESS,
		TESTFUNC_EQUAL,
		TESTFUNC_LESSEQUAL,
		TESTFUNC_GREATER,
		TESTFUNC_NOTEQUAL,
		TESTFUNC_GREATEREQUAL,
		TESTFUNC_ALWAYS,
	};

	enum BlendFactor
	{
		BLENDFCT_ZERO,
		BLENDFCT_ONE,
		BLENDFCT_SRC_COLOR,
		BLENDFCT_ONE_MINUS_SRC_COLOR,
		BLENDFCT_SRC_ALPHA,
		BLENDFCT_ONE_MINUS_SRC_ALPHA,
		BLENDFCT_DST_ALPHA,
		BLENDFCT_ONE_MINUS_DST_ALPHA,
		BLENDFCT_DST_COLOR,
		BLENDFCT_ONE_MINUS_DST_COLOR,
		BLENDFCT_SRC_ALPHA_SATURATE
	};

	enum BasicBlend
	{
		BASICBLEND_UNUSED = -1,
		BASICBLEND_OPAQUE = 0,
		BASICBLEND_TRANSPARENT,
		BASICBLEND_ADDITIVE,
		BASICBLEND_SUBTRACTIVE
	};

	enum TexFilterType
	{
		TEXFILTERTYPE_MIN,
		TEXFILTERTYPE_MAX,
		TEXFILTERTYPE_MIP,
	};

	enum TexFilterMode
	{
		TEXFILTERMODE_NEAREST,
		TEXFILTERMODE_LINEAR,
	};

	enum TexAddrType
	{
		TEXADDRTYPE_S,
		TEXADDRTYPE_T,
	};
	enum TexAddrMode
	{
		TEXADDRMODE_CLAMP,
		TEXADDRMODE_WRAP,
	};


//==================================================================
///
//==================================================================
struct Color4b
{
	union 
	{
		struct {
			u_char	_r, _g, _b, _a;
		};
		u_char	_rgba[4];
	};

	Color4b(){}
	Color4b( u_char r, u_char g, u_char b, u_char a ) :
		_r(r),
		_g(g),
		_b(b),
		_a(a)
	{
	}

	void Set( u_char r, u_char g, u_char b, u_char a )	{ _r = r; _g = g; _b = b; _a = a; }
	void Set( u_char rgba[4] )							{ *((u_int *)_rgba) = *((u_int *)rgba); }
	void Set( u_int rgba )								{ *((u_int *)_rgba) = rgba; }

	void Interpolate( const Color4b &other_col, float coe )
	{
		float	icoe = 1 - coe;
		_rgba[0] = (int)(icoe * _rgba[0] + coe * other_col._rgba[0]);
		_rgba[1] = (int)(icoe * _rgba[1] + coe * other_col._rgba[1]);
		_rgba[2] = (int)(icoe * _rgba[2] + coe * other_col._rgba[2]);
		_rgba[3] = (int)(icoe * _rgba[3] + coe * other_col._rgba[3]);
	}

	Color4b GetInterpolated( const Color4b &other_col, float coe ) const
	{
		float	icoe = 1 - coe;
		return 	Color4b( (int)(icoe * _rgba[0] + coe * other_col._rgba[0]), 
						 (int)(icoe * _rgba[1] + coe * other_col._rgba[1]), 
						 (int)(icoe * _rgba[2] + coe * other_col._rgba[2]), 
						 (int)(icoe * _rgba[3] + coe * other_col._rgba[3]) );
	}

	const u_char	*GetArray() const
	{
		return _rgba;
	}

	Color4b GetScaledRGB( float sca ) const
	{
		int	r = (int)(_r*sca);	PCLAMP( r, 0, 255 );
		int	g = (int)(_g*sca);	PCLAMP( g, 0, 255 );
		int	b = (int)(_b*sca);	PCLAMP( b, 0, 255 );
		int	a = (int)(_a*sca);	PCLAMP( a, 0, 255 );
		return Color4b( r, g, b, a );
	}

	Color4b GetScaledRGBA( float sca ) const
	{
		int	r = (int)(_r*sca);	PCLAMP( r, 0, 255 );
		int	g = (int)(_g*sca);	PCLAMP( g, 0, 255 );
		int	b = (int)(_b*sca);	PCLAMP( b, 0, 255 );
		return Color4b( r, g, b, _a );
	}

	Color4b GetAddRGB( int r, int g, int b ) const
	{
		r += _r; PCLAMP( r, 0, 255 );
		g += _g; PCLAMP( g, 0, 255 );
		b += _b; PCLAMP( b, 0, 255 );
		return Color4b( r, g, b, _a );
	}
/*
	Color4b operator * (const Color4b &cr) const 	{ return Color4b(	_r * cr._r,
																		_g * cr._g,
																		_b * cr._b,
																		_a * cr._a );	}
*/
};

//==================================================================
///
//==================================================================
struct Color4f
{
	union
	{
		struct {
			float	_r, _g, _b, _a;
		};
		float	_rgba[4];
	};

	Color4f( float r, float g, float b, float a ) :
		_r(r), _g(g), _b(b), _a(a)
	{
	}

	Color4f()
	{
	}

	void Set( float r, float g, float b, float a )		{ _r = r; _g = g; _b = b; _a = a; }
	void Set( float rgba[4] )							{ _r = rgba[0]; _g = rgba[1]; _b = rgba[2]; _a = rgba[3]; }
//	void Set( const Vector4 &rgba )						{ _v = rgba; }

	void Interpolate( const Color4b &other_col, float coe )
	{
		float	icoe = 1 - coe;
		_rgba[0] = icoe * _rgba[0] + coe * other_col._rgba[0];
		_rgba[1] = icoe * _rgba[1] + coe * other_col._rgba[1];
		_rgba[2] = icoe * _rgba[2] + coe * other_col._rgba[2];
		_rgba[3] = icoe * _rgba[3] + coe * other_col._rgba[3];
	}
	Color4f GetInterpolated( const Color4f &other_col, float coe ) const
	{
		float	icoe = 1 - coe;
		return Color4f( icoe * _rgba[0] + coe * other_col._rgba[0],
						icoe * _rgba[1] + coe * other_col._rgba[1],
						icoe * _rgba[2] + coe * other_col._rgba[2],
						icoe * _rgba[3] + coe * other_col._rgba[3] );
	}

	Color4f GetScaledRGB(const float sca) const
	{
		return Color4f (_r * sca,
						_g * sca,
						_b * sca,
						_a );
	}
	Color4f GetScaledRGBA(const float sca) const
	{
		return Color4f (_r * sca,
						_g * sca,
						_b * sca,
						_a * sca );
	}

	const float	*GetArray() const
	{
		return _rgba;
	}

	Color4f operator * (const Color4f &cr) const
	{
		return Color4f ( _r * cr._r,
						 _g * cr._g,
						 _b * cr._b,
						 _a * cr._a );
	}

	void operator *= (const Color4f &cr)
	{
		_r *= cr._r;
		_g *= cr._g;
		_b *= cr._b;
		_a *= cr._a;
	}
/*
	Color4f operator * (const float sca) const
	{
		return Color4f ( _r * sca,
						 _g * sca,
						 _b * sca,
						 _a * sca );
	}
*/
};


};

#endif
